// Partial 将属性变为可选
interface Animal {
    age: number;
    weight: string;
    height: string;
    likes: string[];
}

type newDate = Partial<Animal>;

let obj: newDate = {
    age: 12,
};

// Required 反向 Partial
type RequiredData = Required<newDate>;
let p: RequiredData = {
    age: 12,
    weight: '100kg',
    height: '150cm',
    likes: ['吃', '喝', '睡'],
};

// Readonly 只读属性
type ReadonlyData = Readonly<Animal>;
let a: ReadonlyData = {
    age: 12,
    weight: '100kg',
    height: '150cm',
    likes: ['吃', '喝', '睡'],
};
// a.age = 22 // 无法分配到 "age" ，因为它是只读属性。

// Pick 挑选
type PickData = Pick<Animal, 'age' | 'weight'>;
let b: PickData = {
    age: 13,
    weight: '120kg',
};

// Record 键值映射
type Keys = 'dog' | 'cat';
type RecordData = Record<Keys, Animal>;
let c: RecordData = {
    dog: {
        age: 12,
        weight: '100kg',
        height: '150cm',
        likes: ['吃', '喝', '睡'],
    },
    cat: {
        age: 12,
        weight: '100kg',
        height: '150cm',
        likes: ['吃', '喝', '睡'],
    },
};

// Exclude <=> Extract
// type Exclude<T, U> = T extends U ? never : T;
// type Extract<T, U> = T extends U ? T : never;
type A = number | string;
type B = number;

type ExcludeData = Exclude<A, B>; // string
type ExtractData = Extract<A, B>; // number

interface C {
    age: number;
    weight: string;
}
type D = Exclude<keyof C, 'age'>; // weight
type E = Extract<keyof C, 'age'>; // age

// Omit 忽略
type OmitData = Omit<Animal, 'likes'>;
let f: OmitData = {
    age: 12,
    weight: '123',
    height: 'zs',
};

// extends keyof xxx
function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
    return o[name]; // o[name] is of type T[K]
}
function fn<T extends keyof Animal>(params: T) {
    console.log(params);
}
fn('age');
// parmas取值 -> age weight height likes

// Parameters 获取函数中的参数
type Func = (user: number) => number;
type Func1 = () => number;

type params = Parameters<Func>;
type params1 = Parameters<Func1>;

let obj8: params = [1];
let obj9: params1 = [];

// ConstructorParameters 获取类中的参数
class Point {
    public name: string;
    constructor(name: string, age: number) {
        this.name = name;
    }
}

type ConstructorParametersData = ConstructorParameters<typeof Point>;
let arr: ConstructorParametersData = ['zs', 12];

function init(...rest: ConstructorParametersData): ConstructorParametersData {
    const a = rest[0];
    const b = rest[1];
    return [a, b];
}
init('zs', 12);

// ReturnType 推断返回值的类型
type ReturnTypeData = ReturnType<Func>;
type ReturnTypeData1 = ReturnType<Func1>;

// 可辨识联合
interface Square {
    kind: 'square';
    size: number;
}
interface Rectangle {
    kind: 'rectangle';
    width: number;
    height: number;
}
interface Circle {
    kind: 'circle';
    radius: number;
}

type Shape = Square | Rectangle | Circle;

function area(s: Shape): number {
    switch (s.kind) {
        case 'square':
            return s.size * s.size;
        case 'rectangle':
            return s.height * s.width;
        case 'circle':
            return Math.PI * s.radius * 2;
    }
}

const res = area({ kind: 'rectangle', width: 12, height: 30 });
// console.log(res);

export {};
